module module_receive(
   input rst_n,//复位信号
   input receive_en,//使能信号，使能信号默认：零为空闲状态
	///IIC的数据总线与时钟总线
   input sda_0, //输入线
	input scl, //时钟线
	output reg ack,   //应答输出信号
	output reg [7:0] rec_data,  ///输出接收的主机数据
	output reg ack_out_test,    ///输出从机的应答位
	output reg scl_out_test,    ///输出接收的主机时钟线
	output reg sda_out_test     ///输出接收的主机数据线
	
);
  reg [3:0] scl_count;  //分别是数据接收bit位的计数
  reg [3:0] state;     //下一个状态的标志
  reg [3:0] comp;      //校验标志
  reg [1:0] first;     //第一次scl高电平期间是sda线下拉的起始信号，所以要跳过，故做此标记
  reg [7:0] another,dev_addr,re_addr; //第一个是存储实际数据的寄存器
  
  //第二个是从机的设备地址，第二个是寄存器的地址
  
  
///首先进行初始化，之后的rst_n的接收必须一直是0
//always @(posedge scl or negedge rst_n)begin
 always @(scl or rst_n or sda_0 )begin
    scl_out_test=scl;
	 sda_out_test=sda_0;
    if(!rst_n)begin
	   scl_count<=4'b0;
		another<=8'b0;
		dev_addr<=7'b1010_000;
		re_addr<=8'b1111_0100;
		state<=4'b0;
		comp<=4'b0;
		rec_data<=8'b0;
		ack<=1'b0;
		ack_out_test<=1'b0;
		first<=2'b0;
	 end
	 else if(receive_en==1'b1 && first!=2'b0) begin    
	   case (state)
		    4'd0:
				 begin      // 你没有给出处理起始信号的空间，可能会把首先接收到的起始信号当做最高位的数据(但这个问题我也存在，没想好怎么解决，仿真时再看)
					if(scl_count==4'b1000)begin //判断接收数据是否有8bit了
					   if(comp == 4'b0)begin  //第一次要去转到校验从机地址状态
						   //comp<=4'b1;
						   scl_count<=4'b0;
						   state<=4'd1;

						end
						else if(comp == 4'b1)begin  //第二次要去转到校验从机的寄存器地址状态
						   //comp<=4'b2;
							scl_count<=4'b0;
						   state<=4'd2;
						end
						else begin          //大于等于第三次要去转到应答状态
							scl_count<=4'b0;
							state<=4'd3;
						end
					end
					else begin  //未接收满8bit，继续接收
					   if(scl==1'b1)begin
							another[7-scl_count]  <=  sda_0 ; // 先发送高位
							scl_count <=  scl_count + 1'b1 ;   //计算bit数量
							rec_data<=another;
							state=1'b0;                       //未接收满，继续该状态
						end 
						else begin
						   //rec_data<=another;
						   state=1'b0;         //低电平期间继续保持接收状态            
						end
						
					end
				 end
			 4'd1:                                     //校验从机地址（高7位）
			    begin
					 if(scl==1'b0)begin ///应答位需要在低电平期间转换，高电平保持稳定
						 if(another[7:1] ==dev_addr)begin    
						    comp=comp + 1'b1 ;
							 rec_data=8'b0;
							 another=8'b0000_0000;
							 scl_count=4'b0;
							 state=4'd0;
						 end
						 else begin 
						    ack<=1'b1;
							 ack_out_test<=1'b1;
							 state<=4'd4;   
						 end
					 end
					 else begin    //未遇到低电平，持续该状态
						state<=4'd1;  
					 end
				 end
			 4'd2:                                     //校验从机寄存器的地址
			    begin
					 if(scl==1'b0)begin ///应答位需要在低电平期间转换，高电平保持稳定
							if(another ==re_addr)begin  // 校验的是寄存器地址
								 comp=comp + 1'b1 ;
								 rec_data=8'b0;
								 //rec_data<=another;
								 scl_count=4'b0;
								 another=8'b0;
								 state=4'd0;
								 
							 end 
							else begin
							     //rec_data<=another;
								  ack<=1'b1;
							     ack_out_test<=1'b1;
							     state<=4'd4; 
								 end
					 end
					 else begin    //未遇到低电平，持续该状态
						state<=4'd2;  
					 end
				 end 
			 4'd3:                                     //实际数据的应答信号
				 begin
					if(scl==1'b0)begin ///应答位需要在低电平期间转换，高电平保持稳定
						ack<=1'b1;   // 也要有给出非应答的情况
						ack_out_test<=1'b1;
						state=4'd4; 
					end
					else begin
					   state=4'd3; 
					end
					
				 end
			 4'd4:                                     //结束复位
				 begin
					scl_count=4'b0;
					another<=8'b0;
					dev_addr<=7'b1111000;
					re_addr<=8'b11110100;
					state<=4'b0;
					comp<=4'b0;
					first<=2'b0;
					ack<=1'b1;
					ack_out_test<=1'b1;
				 end
	 endcase
  end
  else begin //未接收到使能信号，再次进行初始化复位操作
		//scl_count=4'b0;
		//another<=8'b0;
		//dev_addr<=7'b1111000;
		//re_addr<=8'b11110100;
		//state<=4'b0;
		//comp<=4'b0;
		//rec_data<=8'b0;
		first=2'b01;
  end 
 end
endmodule
  
